# 调用 Sklearn 实现支持向量机
import numpy as np
from sklearn.datasets._samples_generator import make_blobs
from sklearn.datasets._samples_generator import make_circles
from matplotlib import pyplot as plt
from sklearn.svm import SVC

plt.figure(1)
# 生成数据集
# data: 二维列表，点的横纵坐标  target: 点的分类信息
data, target = make_blobs(n_samples = 200, centers = 2, cluster_std = 1.5)
# 画出数据集
plt.scatter(data[:, 0], data[:, 1], c = target)

# 训练 SVM 支持向量机模型
model = SVC(C = 1e10, kernel = 'linear', probability = False)
model.fit(data, target)

# 支持向量机可视化
def plot_svc(model, ax = None, plot_support = True):
    if ax is None:
        ax = plt.gca() # 获得当前图子图
    xlim = ax.get_xlim() # 获取当前图 x 轴的上下限
    ylim = ax.get_ylim()
    x = np.linspace(xlim[0], xlim[1], 30)
    y = np.linspace(ylim[0], ylim[1], 30)
    Y, X = np.meshgrid(y, x) # 融合 xy 坐标
    xy = np.vstack([X.ravel(), Y.ravel()]).T # vstack: 堆叠列表 ravel: 将高维列表展平
    P = model.decision_function(xy).reshape(X.shape) # reshape: 按 X 的形式显示
    ax.contour(X, Y, P, colors = 'k', levels = [-1, 0, 1], alpha = 0.5, linestyles = ['--', '-', '--']) # 画出等值线
    if plot_support:
        ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s = 300, linewidth = 1, facecolors = 'none')
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)

plot_svc(model, plot_support = True)
plt.show()

plt.figure(2)
# 生成非线性可分数据
data, target = make_circles(200, factor = .1, noise = .1)
model = SVC(kernel = 'rbf').fit(data, target)
plt.scatter(data[:, 0], data[:, 1], c = target, cmap = 'autumn', s = 50)

plot_svc(model, plot_support = False)
plt.show()